package com.pocket.insight.service.impl;

import com.pocket.insight.base.dto.ResponseCodeEnum;
import com.pocket.insight.base.exception.BizException;
import com.pocket.insight.base.sql.Dialect;
import com.pocket.insight.base.sql.Vendor;
import com.pocket.insight.base.sql.factory.VendorFactory;
import com.pocket.insight.controller.dto.ConnectionOptionsDto;
import com.pocket.insight.controller.dto.DatasetResultDto;
import com.pocket.insight.controller.dto.PathTableNode;
import com.pocket.insight.controller.dto.SqlParam;
import com.pocket.insight.entity.Connection;
import com.pocket.insight.entity.Dataset;
import com.pocket.insight.mapper.ConnectionMapper;
import com.pocket.insight.service.ConnectionService;
import com.pocket.insight.service.DatasetService;
import jakarta.annotation.Resource;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;

/**
 * @author zhaozhile
 */
@Service
public class ConnectionServiceImpl implements ConnectionService {

    @Resource private DatasetService   datasetService;
    @Resource private ConnectionMapper connectionMapper;


    @Override
    public Connection.MetaConfig verify(ConnectionOptionsDto optionsDto) {
        Connection.MetaConfig config = new Connection.MetaConfig();
        Vendor vendor = VendorFactory.createVendor(optionsDto);
        if (vendor == null) {
            throw new BizException(ResponseCodeEnum.ERROR_DATABASE_NOT_SUPPORTED, optionsDto.getType());
        }
        vendor.verifySocket();
        vendor.checkVersionSupported();
        vendor.setConnectionConfig(optionsDto);

        DatasetResultDto result = vendor.fetchRawQueryData(null, vendor.getPingSql());
        if (result.isConnected()){
            Dialect<?> dialect = vendor.getDialect();
            config.setDbMajorVersion(Long.valueOf(dialect.getMajorVersion()));
            config.setDbMinorVersion(Long.valueOf(dialect.getMinorVersion()));
            config.setDbProductName(dialect.getDbProName());
            config.setDbProductVersion(dialect.getDbProVersion());
        }
        return config;
    }

    @Override
    public Connection save(Connection connection) {
        if (connection.getId() == null){
            connectionMapper.insert(connection);
        } else {
            connectionMapper.updateByPrimaryKey(connection);
        }
        return connection;
    }

    @Override
    public List<Connection> list() {
        return connectionMapper.selectList(new Connection());
    }

    @Override
    public void delete(Long id) {
        Connection connection = getById(id);
        if (connection == null){
            return;
        }
        connectionMapper.deleteByPrimaryKey(id);
    }

    @Override
    public Connection getById(Long id) {
        return connectionMapper.selectByPrimaryKey(id).get();
    }

    @Override
    public List<PathTableNode> getPathTables(Connection connection, Boolean pathOnly, List<String> path) {
        List<PathTableNode> visibleTableList;
        Connection.ConnectionOptions options = connection.getOptions();
        Vendor vendor = Objects.requireNonNull(VendorFactory.createVendor(options), "数据库连接创建异常！");
        if (CollectionUtils.isEmpty(path)) {
            visibleTableList = vendor.getPathTables();
        } else {
            visibleTableList = vendor.getPathTables(path);
        }
        return visibleTableList;
    }

    @Override
    public DatasetResultDto previewDataAndSchema(Connection paramConnection, Dataset dataset, SqlParam sqlParam) {
        return this.datasetService.previewDataAndSchema(dataset, sqlParam);
    }

}
